﻿using Chemistry.Models;
using OPCAutomation;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace Chemistry.WorkFlow
{
    /// <summary>
    /// 加氢还原工艺流程
    /// </summary>
    public class Hydrogenation : FlowBaseAll
    {
        /**
         * 
         * 一票否决：氮气未置换完成，打开氢气阀 属违规操作
         * */

        #region 字段
        private int _sleepfast = 500;
        private int _sleepslow = 1000;//500
        private static int _relayCommand = 0;
        static int _levelNitro_value =0;// 320;
        static int _levelMethanol_value = 0;// 220;
        static double _pressure_value = 0;//压力
        static double _temperature_value = 22;//温度
        static double _flow_value = 0;//流量

        //增加量
        static bool _isgetoverstate1 = false;
        static bool _isgetoverstate2 = false;
        static bool _isgetoverstate3 = false;
        static double _pressure_decrement;
        static double _pressure_increment ;
        static int _levelNitro_crement ;
        static int _levelMethanol_crement ;
        static double _temperature_creament ;
        static double _temperature_decreament;//1
        static double _flow_crement ;

        private Tools.Tool.FlowCommand _flowcommand;
        string _switch1 = string.Empty;
        string _switch2 = string.Empty;
        string _prefix1 = string.Empty;
        string _prefix2 = string.Empty;
        string _llcmd = string.Empty;
        string _ywcmd = string.Empty;
        string _ylcmd = string.Empty;
        string _wdcmd = string.Empty;
        string _aicmd = string.Empty;
        string _relaycmd = string.Empty;
        int _warning1number ;
        int _warning2number ;
        int _fognumber ;
        int _stirnumber;

        static List<Step> _steps = new List<Step>();

        //流程标识
        static bool _isreplaceN2_over = false;

        int open = 48;//1
        int close = 49;//0

        #endregion

        #region 与组态对应阀门状态
        private static bool ValveInNitro_State = false;
        private static bool ValveInMethanol_State = false;
        private static bool ValveOutNitro_State = false;
        private static bool ValveOutMethanol_State = false;
        private static bool ValveInN2_State = false;
        private static bool ValveEmpty_State = false;
        private static bool ValveCold_State = false;
        private static bool ValveInHot_State = false;
        private static bool ValveInH2_State = false;
        private static bool ValveDischarge_State = false;
        private static bool ValveAutoEmpty_State = false;
        private static bool ValveICutoff_State = false;

        private static bool ValveOverNitro_State = false;
        private static bool ValveOverMethanol_State = false;
        private static bool ValveStir_State = false;//搅拌釜状态
        private static bool ValveStop_State = false;//急停按钮状态
        #endregion

        #region OPCItem
        /// <summary>
        /// 硝基物进料阀
        /// </summary>
        OPCItem ValveInNitro_item;
        /// <summary>
        /// 甲醇进料阀
        /// </summary>
        OPCItem ValveInMethanol_item;
        /// <summary>
        /// 硝基物出料阀
        /// </summary>
        OPCItem ValveOutNitro_item;
        /// <summary>
        /// 甲醇出料阀
        /// </summary>
        OPCItem ValveOutMethanol_item;
        /// <summary>
        /// 氮气阀
        /// </summary>
        OPCItem ValveInN2_item;
        /// <summary>
        /// 放空阀
        /// </summary>
        OPCItem ValveEmpty_item;
        /// <summary>
        /// 冷水阀
        /// </summary>
        OPCItem ValveCold_item;
        /// <summary>
        /// 蒸汽阀
        /// </summary>
        OPCItem ValveInHot_item;
        /// <summary>
        /// 氢气进料阀
        /// </summary>
        OPCItem ValveInH2_item;
        /// <summary>
        /// 放料阀
        /// </summary>
        OPCItem ValveDischarge_item;
        /// <summary>
        /// 自动放空阀
        /// </summary>
        OPCItem ValveAutoEmpty_item;
        /// <summary>
        /// 氢气紧急切断阀
        /// </summary>
        OPCItem ValveICutoff_item;
        /// <summary>
        /// 硝基物溢出阀
        /// </summary>
        OPCItem ValveNitro_item;
        /// <summary>
        /// 甲醇溢出阀
        /// </summary>
        OPCItem ValveMethanol_item;

        private OPCItem ValveStir_item;
        private OPCItem ValveStop_item;

        //label
        OPCItem LabelNitro_item;
        OPCItem LabelMethanol_item;
        OPCItem LabelPresssure_item;
        OPCItem LabelTemperature_item;
        OPCItem LabelFlow_item;
        OPCItem LabelOxygen_item;

        //闪烁
        OPCItem FlashCatalyst_item;
        OPCItem FlashStir_item;
        OPCItem FlashPressure_item;
        OPCItem FlashTemperature_item;
        OPCItem FlashWarning_item;

        //管道流动item
        OPCItem FlowInNitro_item;
        OPCItem FlowInMethanol_item;
        OPCItem FlowOutMethanol_item;
        OPCItem FlowOutNitro_item;
        OPCItem FlowOutEmpty_item;
        OPCItem FlowInCold_item;
        OPCItem FlowInHot_item;
        OPCItem FlowInH2_item;
        OPCItem FlowDischarge_item;
        OPCItem FlowInN2_item;

        #endregion

        #region 初始化
        public Hydrogenation(OPCServer opcserver, SerialPort port,bool isinner)
        {
            _opcServer = opcserver;
            _serialPort = port;
            Isinner = isinner;

            InitFiled();
            InitOPC();
            InitOpcItem();
            InitSignal();
        }
        private void InitFlowCommandData()
        {
            _flowcommand = Tools.Tool.GetFlowCommand(this.GetType().Name);
            _switch1 = _flowcommand.Items.SingleOrDefault(i => i.Name == "switch1").Value;
            _switch2 = _flowcommand.Items.SingleOrDefault(i => i.Name == "switch2").Value;
            _prefix1 = _flowcommand.Items.SingleOrDefault(i => i.Name == "prefix1").Value;
            _prefix2 = _flowcommand.Items.SingleOrDefault(i => i.Name == "prefix2").Value;
            _llcmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "llcmd").Value;
            _ywcmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "ywcmd").Value;
            _ylcmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "ylcmd").Value;
            _wdcmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "wdcmd").Value;
            _aicmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "aicmd").Value;
            _relaycmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "relaycmd").Value;
            _warning1number = int.Parse(_flowcommand.Items.SingleOrDefault(i => i.Name == "warning1").Value);
            _warning2number = int.Parse(_flowcommand.Items.SingleOrDefault(i => i.Name == "warning2").Value);
            _fognumber = int.Parse(_flowcommand.Items.SingleOrDefault(i => i.Name == "fog").Value);
            _stirnumber = int.Parse(_flowcommand.Items.SingleOrDefault(i => i.Name == "stir").Value);
        }

        private static void InitFiled()
        {
            _isgetoverstate1 = false;
            _isgetoverstate2 = false;
            _isgetoverstate3 = false;
            _relayCommand = 0;
            _levelNitro_value = 340;//340;
            _levelMethanol_value = 240;// 240;
            _pressure_value = 0;//压力
            _temperature_value = 22;//温度
            _flow_value = 0;//流量

            _pressure_decrement = 0.02;//0.02
            _pressure_increment = 0.02;//0.01
            _levelNitro_crement = 10;
            _levelMethanol_crement = 10;
            _temperature_creament = 1;//2
            _temperature_decreament = 1;//1
            _flow_crement = 1;
        }

        private void InitOpcItem()
        {
            ValveOutNitro_item = GetItem(FiledName.ValveOutNitro); ValveOutNitro_item.Close();
            ValveOutMethanol_item = GetItem(FiledName.ValveOutMethanol); ValveOutMethanol_item.Close();
            ValveInN2_item = GetItem(FiledName.ValveInN2); ValveInN2_item.Close();
            ValveEmpty_item = GetItem(FiledName.ValveEmpty); ValveEmpty_item.Open();
            var ValveCold = Convert.ToInt32(ReadItem(FiledName.ValveCold));
            ValveCold_item = GetItem(FiledName.ValveCold); ValveCold_item.Close();
            ValveInHot_item = GetItem(FiledName.ValveInHot); ValveInHot_item.Close();
            ValveInH2_item = GetItem(FiledName.ValveInH2); ValveInH2_item.Close();
            ValveDischarge_item = GetItem(FiledName.ValveDischarge); ValveDischarge_item.Close();
            ValveAutoEmpty_item = GetItem(FiledName.ValveAutoEmpty); ValveAutoEmpty_item.Close();
            ValveICutoff_item = GetItem(FiledName.ValveICutoff); ValveICutoff_item.Open();
            ValveInNitro_item = GetItem(FiledName.ValveInNitro); ValveInNitro_item.Close();
            ValveInMethanol_item = GetItem(FiledName.ValveInMethanol); ValveInMethanol_item.Close();
            ValveNitro_item = GetItem(FiledName.ValveOverNitro); ValveNitro_item.Close();
            ValveMethanol_item = GetItem(FiledName.ValveOverMethanol); ValveMethanol_item.Close();
            ValveStir_item = GetItem(FiledName.ValveStir);
            ValveStir_item.Close();
            ValveStop_item = GetItem(FiledName.ValveStop);
            ValveStop_item.Close();

            //管道item
            FlowInNitro_item = GetItem(FiledName.FlowInNitro); FlowInNitro_item.Close();
            FlowInMethanol_item = GetItem(FiledName.FlowInMethanol); FlowInMethanol_item.Close();
            FlowOutMethanol_item = GetItem(FiledName.FlowOutMethanol); FlowOutMethanol_item.Close();
            FlowOutNitro_item = GetItem(FiledName.FlowOutNitro); FlowOutNitro_item.Close();
            FlowOutEmpty_item = GetItem(FiledName.FlowOutEmpty); FlowOutEmpty_item.Close();
            FlowInCold_item = GetItem(FiledName.FlowInCold); FlowInCold_item.Close();
            FlowInHot_item = GetItem(FiledName.FlowInHot); FlowInHot_item.Close();
            FlowInH2_item = GetItem(FiledName.FlowInH2); FlowInH2_item.Close();
            FlowDischarge_item = GetItem(FiledName.FlowDischarge); FlowDischarge_item.Close();
            FlowInN2_item = GetItem(FiledName.FlowInN2); FlowInN2_item.Close();

            //Label
            LabelNitro_item = GetItem(FiledName.LabelNitro); LabelNitro_item.Write(_levelNitro_value);
            LabelMethanol_item = GetItem(FiledName.LabelMethanol); LabelMethanol_item.Write(_levelMethanol_value);
            LabelPresssure_item = GetItem(FiledName.LabelPresssure); LabelPresssure_item.Write(_pressure_value);
            LabelTemperature_item = GetItem(FiledName.LabelTemperature); LabelTemperature_item.Write(_temperature_value);
            LabelFlow_item = GetItem(FiledName.LabelFlow); LabelFlow_item.Write(0);
            LabelOxygen_item = GetItem(FiledName.LabelOxygen); LabelOxygen_item.Write(21);

            //闪烁item
            FlashCatalyst_item = GetItem(FiledName.FlashCatalyst); FlashCatalyst_item.Close();
            FlashStir_item = GetItem(FiledName.FlashStir); FlashStir_item.Close();
            FlashPressure_item = GetItem(FiledName.FlashPressure);
            FlashPressure_item.Close();
            FlashTemperature_item = GetItem(FiledName.FlashTemperature);
            FlashTemperature_item.Close();
            FlashWarning_item = GetItem(FiledName.FlashWarning);
            FlashWarning_item.Write(0);
        }
        private async Task InitServerData()
        {
            var abnormalRusult = await GetAbnormalModel(GetType().Name);
            if (abnormalRusult != null && abnormalRusult.status == 0)
                _abnormals = abnormalRusult.abnormals;
            var d = await GetDetailModel(GetType().Name);
            if (d != null && d.status == 0)
                _details = d.details;
        }

        private void InitSignal()
        {
            if (Isinner)
            {
                open = 1;
                close = 0;
                ListenSignal();
                
            }
            else
            {
                InitFlowCommandData();
                _serialPort.DataReceived += _serialPort_DataReceivedTest;
                InitOpcItemWithSerialPort();
                ListenSerialPortAndAbnormalData();
                open = 48;
                close = 49;
            }
        }

        private void InitOpcItemWithSerialPort()
        {
            SPYWValue(1, _levelNitro_value);
            SPYWValue(2, _levelMethanol_value);
            SpPressureValue(0.01);
            SpTemperatureValue(_temperature_value);
            Thread.Sleep(200);
            SpFlowValue(0);
            //关闭所有继电器
            _relayCommand = 0;
            SPWriteTool(_relayCommand);
        }

        #endregion

        #region 监听步骤，计分
        private void ListenSerialPortAndAbnormalData()
        {
            string chkcmd_1 = _flowcommand.Items.SingleOrDefault(i => i.Name == "chkcmd1").Value;  //"#RYW21651&";
            string chkcmd_2 = _flowcommand.Items.SingleOrDefault(i => i.Name == "chkcmd2").Value;//"#RYW21652&";

            Task listSerialPortState = new Task(
                () =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (_serialPort.IsOpen)
                        {
                            lock (this)
                            {
                                Thread.Sleep(150);
                                try
                                {
                                    _serialPort.Write(chkcmd_1);
                                }
                                catch (Exception)
                                { }

                            }
                        }

                        if (_serialPort.IsOpen)
                        {
                            lock (this)
                            {
                                Thread.Sleep(150);
                                try
                                {
                                    _serialPort.Write(chkcmd_2);
                                }
                                catch (Exception)
                                { }

                            }
                        }
                    }
                });

            listSerialPortState.Start();
        }

        int _replace_count1 = 1;
        int _replace_count2 = -1;
        bool _can_open_empty1 = false;
        bool _can_open_empty2 = false;
        bool _isListenSingnalover = false;
        private void ListenSignal()
        {
            Task t = new Task(() =>
            {
                while (!_listenCts.IsCancellationRequested)
                {
                    var valveInNitro = Convert.ToInt32(ReadItem(FiledName.ValveInNitro));
                    var ValveInMethanol = Convert.ToInt32(ReadItem(FiledName.ValveInMethanol));
                    var ValveOutNitro = Convert.ToInt32(ReadItem(FiledName.ValveOutNitro));
                    var ValveOutMethanol = Convert.ToInt32(ReadItem(FiledName.ValveOutMethanol));
                    var ValveInN2 = Convert.ToInt32(ReadItem(FiledName.ValveInN2));
                    var ValveEmpty = Convert.ToInt32(ReadItem(FiledName.ValveEmpty));
                    var ValveCold = Convert.ToInt32(ReadItem(FiledName.ValveCold));
                    var ValveInHot = Convert.ToInt32(ReadItem(FiledName.ValveInHot));
                    var ValveInH2 = Convert.ToInt32(ReadItem(FiledName.ValveInH2));
                    var ValveDischarge = Convert.ToInt32(ReadItem(FiledName.ValveDischarge));
                    var ValveAutoEmpty = Convert.ToInt32(ReadItem(FiledName.ValveAutoEmpty));
                    var ValveICutoff = Convert.ToInt32(ReadItem(FiledName.ValveICutoff));
                    var ValveOverNitro = Convert.ToInt32(ReadItem(FiledName.ValveOverNitro));
                    var ValveOverMethanol = Convert.ToInt32(ReadItem(FiledName.ValveOverMethanol));
                    var ValveStir = Convert.ToInt32(ReadItem(FiledName.ValveStir));
                    var ValveStop = Convert.ToInt32(ReadItem(FiledName.ValveStop));

                    ValveInNitro_State = valveInNitro == open;
                    ValveInMethanol_State = ValveInMethanol == open;
                    ValveOutNitro_State = ValveOutNitro == open;
                    ValveOutMethanol_State = ValveOutMethanol == open;
                    ValveInN2_State = ValveInN2 == open;
                    ValveEmpty_State = ValveEmpty == open;//1
                    ValveCold_State = ValveCold == open;
                    ValveInHot_State = ValveInHot == open;
                    ValveInH2_State = ValveInH2 == open;
                    ValveDischarge_State = ValveDischarge == open;
                    ValveAutoEmpty_State = ValveAutoEmpty == open;
                    ValveICutoff_State = ValveICutoff == open;
                    ValveOverNitro_State = ValveOverNitro == open;
                    ValveOverMethanol_State = ValveOverMethanol == open;
                    ValveStir_State = ValveStir == open;
                    ValveStop_State = ValveStop == open;

                    DateTime dtnow = DateTime.Now;
                    Step step = new Step()
                    {
                        Status = new Dictionary<Enum, double>()
                    {
                       {StatusName.氮气阀1,-1},
                       {StatusName.氮气阀2,-1},
                       {StatusName.氮气阀3,-1},
                       {StatusName.氮气阀4,-1},

                       {StatusName.放空阀1,-1},
                       {StatusName.放空阀2,-1},
                       {StatusName.放空阀3,-1},
                       {StatusName.放空阀4,-1},
                       
                       {StatusName.硝基物进料阀,valveInNitro},
                       {StatusName.硝基物放料阀,ValveOutNitro},
                       {StatusName.甲醇进料阀,ValveInMethanol},
                       {StatusName.甲醇放料阀,ValveOutMethanol},

                       {StatusName.放料阀,ValveDischarge},
                       {StatusName.甲醇液位, _levelMethanol_value},
                       {StatusName.搅拌阀,ValveStir},
                       {StatusName.紧急切断阀,ValveICutoff},
                       {StatusName.冷水阀,ValveCold},
                       {StatusName.流量,_flow_value},
                       {StatusName.氢气阀,ValveInH2},
                       {StatusName.温度, _temperature_value},
                       {StatusName.硝基物液位,_levelNitro_value},
                       {StatusName.压力,_pressure_value},
                       {StatusName.蒸汽阀, ValveInHot},
                       {StatusName.自动放空阀, ValveAutoEmpty}
                    },
                        Date = dtnow,
                    };

                    FillStep(ValveInN2, ValveEmpty, step);
                    
                    _steps.Add(step);

                    _isListenSingnalover = true;
                    Thread.Sleep(_sleepfast);
                }
            });
            t.Start();

            //ListAbnormal();
        }
        int _valveInNitro = -1,
                       _valveInMethanol = -1,
                       _valveOutNitro = -1,
                       _valveOutMethanol = -1,
                       _valveStir = -1,
                       _valveStop = -1,
                       _valveInN2 = -1,
                       _valveEmpty = -1,
                       _valveCold = -1,
                       _valveInHot = -1,
                       _valveInH2 = -1,
                       _valveDischarge = -1,
                       _valveAutoEmpty = -1,
                       _valveICutoff = -1;

        private string _recv = String.Empty;

        private void _serialPort_DataReceivedTest(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(500);
            if (!_serialPort.IsOpen)
                return;
            int n = _serialPort.BytesToRead;
            byte[] data = new byte[n];
            _serialPort.Read(data, 0, data.Length);

            string temp = Encoding.Default.GetString(data);
            Console.WriteLine("收到：" + temp);
            Match match = Regex.Match(temp, @"\d{5}_\d{3}");
            while (match.Success)
            {
                Console.WriteLine(match.Value);
                ParseSpData(match.Value);
                match = match.NextMatch();
            }
        }

        private void ParseSpData(string data)
        {
            Match match = Regex.Match(data, @"\d{5}_\d{3}");
            if (match.Success)
            {
                string s = match.Groups[0].Value.Split('_')[1];
                int v = Convert.ToInt32(s);
                string r = Convert.ToString(v, 2).PadLeft(8, '0');
                string first = match.Groups[0].Value.Split('_')[0];

                if (first == _prefix1)
                {
                    //通用接线

                    #region 21651

                    _valveOutNitro = Convert.ToInt32(r[0]);
                    _valveEmpty = Convert.ToInt32(r[1]);
                    _valveStop = Convert.ToInt32(r[2]); //2
                    _valveStir = Convert.ToInt32(r[3]); //3
                    _valveInMethanol = Convert.ToInt32(r[4]);
                    _valveOutMethanol = Convert.ToInt32(r[5]); //5
                    _valveInH2 = Convert.ToInt32(r[6]);
                    _valveAutoEmpty = Convert.ToInt32(r[7]);

                    ValveOutNitro_State = _valveOutNitro == open;
                    ValveEmpty_State = _valveEmpty == open;
                    ValveStir_State = _valveStir == open;
                    ValveStop_State = _valveStop == open;
                    ValveInMethanol_State = _valveInMethanol == open;
                    ValveOutMethanol_State = _valveOutMethanol == open;
                    ValveAutoEmpty_State = _valveAutoEmpty == open;
                    ValveInH2_State = _valveInH2 == open;
                    _isgetoverstate1 = true;

                    #endregion
                }
                else if (first == _prefix2)
                {
                    //通用接线

                    #region 21652

                    _valveInHot = Convert.ToInt32(r[1]);
                    _valveInNitro = Convert.ToInt32(r[2]);
                    _valveDischarge = Convert.ToInt32(r[3]);
                    _valveCold = Convert.ToInt32(r[4]);
                    _valveICutoff = Convert.ToInt32(r[5]);
                    _valveInN2 = Convert.ToInt32(r[6]);

                    ValveInHot_State = _valveInHot == open;
                    ValveInNitro_State = _valveInNitro == open;
                    ValveDischarge_State = _valveDischarge == open;
                    ValveCold_State = _valveCold == open;
                    ValveICutoff_State = _valveICutoff == open;
                    ValveInN2_State = _valveInN2 == open;
                    _isgetoverstate2 = true;

                    #endregion

                }
                #region Add Step

                DateTime dtnow = DateTime.Now;
                Step step = new Step()
                {
                    Status = new Dictionary<Enum, double>()
                    {
                        {StatusName.氮气阀1, -1},
                        {StatusName.氮气阀2, -1},
                        {StatusName.氮气阀3, -1},
                        {StatusName.氮气阀4, -1},

                        {StatusName.放空阀1, -1},
                        {StatusName.放空阀2, -1},
                        {StatusName.放空阀3, -1},
                        {StatusName.放空阀4, -1},

                        {StatusName.甲醇液位, _levelMethanol_value},
                        {StatusName.流量, _flow_value},
                        {StatusName.温度, _temperature_value},
                        {StatusName.硝基物液位, _levelNitro_value},
                        {StatusName.压力, _pressure_value},


                        {StatusName.硝基物进料阀, _valveInNitro},
                        {StatusName.硝基物放料阀, _valveOutNitro},
                        {StatusName.甲醇进料阀, _valveInMethanol},
                        {StatusName.甲醇放料阀, _valveOutMethanol},
                        {StatusName.搅拌阀, _valveStir},
                        {StatusName.紧急切断阀, _valveICutoff},
                        {StatusName.蒸汽阀, _valveInHot},
                        {StatusName.冷水阀, _valveCold},
                        {StatusName.氢气阀, _valveInH2},
                        {StatusName.自动放空阀, _valveAutoEmpty},
                        {StatusName.放料阀, _valveDischarge},
                    },
                    Date = dtnow,
                };
                FillStep(_valveInN2, _valveEmpty, step);
                _steps.Add(step);

                #endregion
            }
        }


        private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int n = _serialPort.BytesToRead;
            byte[] data = new byte[n];
            _serialPort.Read(data, 0, data.Length);

            string temp = Encoding.Default.GetString(data);

            if (!temp.EndsWith("\n"))
            {
                _recv += temp;
            }
            else
            {
                Match match = Regex.Match(_recv, @"\d{5}_\d{3}");
                if (match.Success)
                {
                    string s = match.Groups[0].Value.Split('_')[1];
                    int v = Convert.ToInt32(s);
                    string r = Convert.ToString(v, 2).PadLeft(8, '0');
                    string first = match.Groups[0].Value.Split('_')[0];

                    if (first == _prefix1)
                    {
                        //通用接线
                        #region 21651
                        _valveOutNitro = Convert.ToInt32(r[0]);
                        _valveEmpty = Convert.ToInt32(r[1]);
                        _valveStop = Convert.ToInt32(r[2]); //2
                        _valveStir = Convert.ToInt32(r[3]); //3
                        _valveInMethanol = Convert.ToInt32(r[4]);
                        _valveOutMethanol = Convert.ToInt32(r[5]); //5
                        _valveInH2 = Convert.ToInt32(r[6]);
                        _valveAutoEmpty = Convert.ToInt32(r[7]);

                        ValveOutNitro_State = _valveOutNitro == open;
                        ValveEmpty_State = _valveEmpty == open;
                        ValveStir_State = _valveStir == open;
                        ValveStop_State = _valveStop == open;
                        ValveInMethanol_State = _valveInMethanol == open;
                        ValveOutMethanol_State = _valveOutMethanol == open;
                        ValveAutoEmpty_State = _valveAutoEmpty == open;
                        ValveInH2_State = _valveInH2 == open;
                        _isgetoverstate1 = true;
                        #endregion
                    }
                    else if (first == _prefix2)
                    {
                        //通用接线
                        #region 21652
                        _valveInHot = Convert.ToInt32(r[1]);
                        _valveInNitro = Convert.ToInt32(r[2]);
                        _valveDischarge = Convert.ToInt32(r[3]);
                        _valveCold = Convert.ToInt32(r[4]);
                        _valveICutoff = Convert.ToInt32(r[5]);
                        _valveInN2 = Convert.ToInt32(r[6]);

                        ValveInHot_State = _valveInHot == open;
                        ValveInNitro_State = _valveInNitro == open;
                        ValveDischarge_State = _valveDischarge == open;
                        ValveCold_State = _valveCold == open;
                        ValveICutoff_State = _valveICutoff == open;
                        ValveInN2_State = _valveInN2 == open;
                        _isgetoverstate2 = true;
                        #endregion

                    }


                    #region Add Step
                    DateTime dtnow = DateTime.Now;
                    Step step = new Step()
                    {
                        Status = new Dictionary<Enum, double>()
                        {
                            {StatusName.氮气阀1, -1},
                            {StatusName.氮气阀2, -1},
                            {StatusName.氮气阀3, -1},
                            {StatusName.氮气阀4, -1},

                            {StatusName.放空阀1, -1},
                            {StatusName.放空阀2, -1},
                            {StatusName.放空阀3, -1},
                            {StatusName.放空阀4, -1},

                            {StatusName.甲醇液位, _levelMethanol_value},
                            {StatusName.流量, _flow_value},
                            {StatusName.温度, _temperature_value},
                            {StatusName.硝基物液位, _levelNitro_value},
                            {StatusName.压力, _pressure_value},


                            {StatusName.硝基物进料阀, _valveInNitro},
                            {StatusName.硝基物放料阀, _valveOutNitro},
                            {StatusName.甲醇进料阀, _valveInMethanol},
                            {StatusName.甲醇放料阀, _valveOutMethanol},
                            {StatusName.搅拌阀, _valveStir},
                            {StatusName.紧急切断阀, _valveICutoff},
                            {StatusName.蒸汽阀, _valveInHot},
                            {StatusName.冷水阀, _valveCold},
                            {StatusName.氢气阀, _valveInH2},
                            {StatusName.自动放空阀, _valveAutoEmpty},
                            {StatusName.放料阀, _valveDischarge},
                        },
                        Date = dtnow,
                    };
                    FillStep(_valveInN2, _valveEmpty, step);
                    _steps.Add(step); 
                    #endregion
                }
            }
        }

        private void FillStep(int valveInN2, int valveEmpty, Step step)
        {
            if (_replace_count1 == 1)
            {
                step.Status[StatusName.氮气阀1] = valveInN2;
                if (_can_open_empty1)
                {
                    if (_pressure_value == 0)
                    {
                        step.Status[StatusName.放空阀1] = valveEmpty;
                        LabelOxygen_item.Write(5);
                        _replace_count1 = 2;
                        _can_open_empty1 = false;
                    }
                }
            }
            else if (_replace_count1 == 2)
            {
                step.Status[StatusName.氮气阀2] = valveInN2;
                if (_can_open_empty1)
                {
                    if (_pressure_value == 0 )
                    {
                        step.Status[StatusName.放空阀2] = valveEmpty;
                        LabelOxygen_item.Write(1);
                        _replace_count1 = 3;//之后不再计算
                        _isreplaceN2_over = true;
                    }
                }
            }

            //反应后氮气置换
            if (_replace_count2 == 1)
            {
                step.Status[StatusName.氮气阀3] = valveInN2;
                if (_can_open_empty2)
                {
                    if (_pressure_value == 0)
                    {
                        step.Status[StatusName.放空阀3] = valveEmpty;
                        _replace_count2 = 2;
                        _can_open_empty2 = false;
                    }
                }
            }
            else if (_replace_count2 == 2 )
            {
                step.Status[StatusName.氮气阀4] = valveInN2;
                if (_can_open_empty2)
                {
                    if (_pressure_value == 0)
                    {
                        step.Status[StatusName.放空阀4] = valveEmpty;
                        _replace_count2 = 3;//之后不再计算
                    }
                }
            }
        }

        #endregion

        #region 触发、处理异常的方法

        #region 处理温度异常

        public override void TemperatureAbnormal()
        {
            this.BeginTempretureAbnormal();
        }

        private void BeginTempretureAbnormal()
        {
            _warningDicionary.Add(WarningType.温度异常, false);
            Task.Run(() =>
            {
                while (_temperature_value < 125)
                {
                    _temperature_value += 5;
                    LabelTemperature_item.Write(_temperature_value);
                    SpTemperatureValue(_temperature_value);
                    Thread.Sleep(_sleepfast);
                }
                BeginWarning(WarningType.温度异常);
                FlashTemperature_item.StartFlow();
                HandleTempretureAbnormal();
            });
        }

        private void HandleTempretureAbnormal()
        {
            Task.Run(
                () =>
                    {
                        Parallel.Invoke(CloseHotValve, OpenColdValve);
                        StopWarning(WarningType.温度异常);
                        _warningDicionary[WarningType.温度异常] = true;
                    });
        }

        private void OpenColdValve()
        {
            while (!_listenCts.IsCancellationRequested)
            {
                if (_temperature_value <= 50)
                {
                    AddCompose("处理温度异常：打开冷水阀");
                    break;
                }
                Thread.Sleep(_sleepslow);
            }
        }

        private void CloseHotValve()
        {
            while (!_listenCts.IsCancellationRequested) 
            {
                if (!ValveInHot_State)
                {
                    AddCompose("处理温度异常：关闭蒸汽阀");
                    break;
                }
                Thread.Sleep(_sleepslow);
            }
        }

        #endregion

        #region 触发、处理压力异常

        public override void PressureAbnormal()
        {
            this.BeginPressureAbnormal();
        }

        private void BeginPressureAbnormal()
        {
            _warningDicionary.Add(WarningType.压力异常, false);
            Task.Run(() =>
            {
                while (_pressure_value < 2.5)
                {
                    _pressure_value += 0.1;
                    LabelPresssure_item.Write(_pressure_value);
                    SpPressureValue(_pressure_value);
                    Thread.Sleep(_sleepfast);
                }
                BeginWarning(WarningType.压力异常);
                FlashPressure_item.StartFlow();
                HandlePressureAbnormal();
            });
        }

        private void HandlePressureAbnormal()
        {
            Task.Run(
                () =>
                    {
                        Parallel.Invoke(OpenAirValve, CloseH2Valve);
                        StopWarning(WarningType.压力异常);
                        _warningDicionary[WarningType.压力异常] = true;
                    });
        }
        void OpenAirValve()
        {
            _pressure_decrement = 0.02;//加快降压
            //打开放空阀
            while (!_listenCts.IsCancellationRequested)
            {
                if (ValveEmpty_State)
                {
                    if (_pressure_value <= 0.01)
                    {
                        AddCompose("处理压力异常：打开放空阀");
                        break;
                    }
                }
                //else
                //{
                //    if (_pressure_value >= 0 && _pressure_value < const_pg)
                //    {
                //        SendMessage("反应釜压力未降至0，请打开放空阀");
                //    }
                //}
                Thread.Sleep(_sleepfast);
            }
        }
        private void AutoOpenAirValve()
        {
            double og_value = Convert.ToDouble(ReadItem(FiledName. LabelOxygen));
            ValveAutoEmpty_item.Open();
            FlowOutEmpty_item.StartFlow();
            while (!_listenCts.IsCancellationRequested)
            {
                _pressure_value -= 0.01;
                if (_pressure_value < 0)
                    _pressure_value = 0;
                LabelPresssure_item.Write(_pressure_value);

                og_value++;
                if (og_value > 21)
                    og_value = 21;
                LabelOxygen_item.Write(og_value);

                if (_pressure_value == 0 && og_value == 21)
                    break;
                Thread.Sleep(_sleepslow);
            }
        }

        private void CloseH2Valve()
        {
            while (!_listenCts.IsCancellationRequested)
            {
                if (!ValveInH2_State)
                {
                    AddCompose("处理压力异常：关闭氢气阀");
                    break;
                }
                    
                Thread.Sleep(_sleepfast);
            }
        }
        #endregion

        #region 泄漏
        void BeginLeakAbnormal()
        {
            _isleakAbnormal = false;
            BeginWarning(WarningType.泄漏);
            BeginLeak();
            _warningDicionary.Add(WarningType.泄漏, false);
            HandleLeakAbnormal();
        }

        private void HandleLeakAbnormal()
        {
            //打开急停按钮
            while (!_listenCts.IsCancellationRequested)//true
            {
                if (ValveStop_State)
                {
                    AddCompose("处理泄漏异常：按下急停按钮");
                    break;
                }
                Thread.Sleep(_sleepfast);
            }
            //关闭氢气和蒸汽
            Parallel.Invoke(() =>
            {
                while (!_listenCts.IsCancellationRequested)//true
                {
                    if (!ValveInHot_State)
                    {
                        AddCompose("处理泄漏异常：关闭蒸汽阀");
                        break;
                    }
                    Thread.Sleep(_sleepfast);
                }
            }, () =>
            {
                while (!_listenCts.IsCancellationRequested)//true
                {
                    if (!ValveInH2_State)
                    {
                        AddCompose("处理泄漏异常：关闭氢气阀");
                        break;
                    }
                    Thread.Sleep(_sleepfast);
                }
            });
            
            StopWarning(WarningType.泄漏);
            _warningDicionary[WarningType.泄漏] = true;
        }

        #endregion


        #endregion

        #region 公共方法
        public override void Begin()
        {
            ListenOpcRelation();
        }
        public override async Task<string> CheckDefault()
        {
            StringBuilder builder = new StringBuilder();
              await Task.Run(() =>
              {
                  if (!Isinner)
                  {
                      while (!_isgetoverstate1 || !_isgetoverstate2 )
                      {
                          Thread.Sleep(_sleepslow);
                      }
                  }
                  else
                  {
                      while (!_isListenSingnalover)
                      {
                          Thread.Sleep(_sleepslow);
                      }
                  }
                  
                  if (ValveInNitro_State)
                      builder.AppendLine("硝基物进料阀未关闭");
                  if (ValveInMethanol_State)
                      builder.AppendLine("甲醇进料阀未关闭");
                  if (ValveOutNitro_State)
                      builder.AppendLine("硝基物放料阀未关闭");
                  if (ValveOutMethanol_State)
                      builder.AppendLine("甲醇放料阀未关闭");
                  if (ValveInN2_State)
                      builder.AppendLine("氮气阀未关闭");
                  if (!ValveEmpty_State)
                      builder.AppendLine("手动放空阀未打开");
                  if (ValveCold_State)
                      builder.AppendLine("冷水阀未关闭");
                  if (ValveInHot_State)
                      builder.AppendLine("蒸汽阀未关闭");
                  if (ValveInH2_State)
                      builder.AppendLine("氢气阀未关闭");
                  if (ValveDischarge_State)
                      builder.AppendLine("放料阀未关闭");
                  if (ValveAutoEmpty_State)
                      builder.AppendLine("自动放空阀未关闭");
                  if (!ValveICutoff_State)
                      builder.AppendLine("紧急切断阀未打开");
                  if (ValveStir_State)
                      builder.AppendLine("搅拌按钮未关闭");
                  if (ValveStop_State)
                      builder.AppendLine("急停按钮未关闭");

              });
            await InitServerData();
            if(_details==null||_abnormals==null)
                builder.AppendLine("可能由于网络原因，导致获取数据失败，请点击\"确定\"按钮 尝试重新获取");

            return builder.ToString();
        }

        public override void Over()
        {
            Close();
            CalcFlowAndStep();
            Score = CalcScore();
            CloseAllRelay();
            Finish();
        }
        public override void Close()
        {
            this._listenCts.Cancel();
            base.Close();
            if (_serialPort != null)
            {
                //_serialPort.DataReceived -= _serialPort_DataReceived;
                _serialPort.DataReceived -= _serialPort_DataReceivedTest;
                _serialPort.Close();
            }
        }
        private void ListenOpcRelation()
        {
            ThreadPool.QueueUserWorkItem((o) =>
            {
                bool is_reaction_over = false;
                bool can_open_n2 = false;
               

                #region 搅拌釜状态
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (!ValveStir_State)
                        {
                            StopStir();
                            if (!Isinner)
                                ValveStir_item.Close();
                        }
                        else
                        {
                            if (!Isinner) ValveStir_item.Open();
                            
                            BeginStir();

                            FlashStir_item.Open();
                            Thread.Sleep(300);
                            FlashStir_item.Close();
                            Thread.Sleep(300);
                        }
                        Thread.Sleep(_sleepslow);
                    }
                });

                #endregion

                #region 硝基物进料
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveInNitro_State)
                        {
                            if (!Isinner) ValveInNitro_item.Open();
                            FlowInNitro_item.StartFlow();
                            _levelNitro_value += _levelNitro_crement;
                            if (_levelNitro_value <= 600)
                            {
                                LabelNitro_item.Write(_levelNitro_value);
                                SPYWValue(1, _levelNitro_value);
                            }
                            else if (_levelNitro_value > 650)
                            {
                                AddCompose("硝基物进料：液位高于650，未关闭硝基物进料阀");
                                BeginWarning(WarningType.硝基物液位过高);
                            }
                        }
                        else
                        {
                            if (!Isinner) ValveInNitro_item.Close();
                            StopWarning(WarningType.硝基物液位过高);
                            FlowInNitro_item.StopFlow();
                            if (_levelNitro_value > 650)
                            {
                                _levelNitro_value = 600;
                                LabelNitro_item.Write(_levelNitro_value);
                                SPYWValue(1, _levelNitro_value);
                            }
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });
                #endregion

                #region 甲醇进料
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveInMethanol_State)
                        {
                            if (!Isinner) ValveInMethanol_item.Open();
                            FlowInMethanol_item.StartFlow();
                            _levelMethanol_value += _levelMethanol_crement;

                            if (_levelMethanol_value <= 400)
                            {
                                LabelMethanol_item.Write(_levelMethanol_value);
                                SPYWValue(2, _levelMethanol_value);
                            }
                            else if (_levelMethanol_value > 450)
                            {
                                AddCompose("甲醇进料：液位高于450，未关闭甲醇进料阀");
                                BeginWarning(WarningType.甲醇液位过高);
                            }
                        }
                        else
                        {
                            if (!Isinner) ValveInMethanol_item.Close();
                            StopWarning(WarningType.甲醇液位过高);
                            FlowInMethanol_item.StopFlow();
                            if (_levelMethanol_value > 450)
                            {
                                _levelMethanol_value = 400;
                                LabelMethanol_item.Write(_levelMethanol_value);
                                SPYWValue(2, _levelMethanol_value);
                            }
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });

                #endregion

                #region 硝基物出料
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)//true
                    {
                        if (ValveOutNitro_State)
                        {
                            if (!Isinner) ValveOutNitro_item.Open();
                            FlowOutNitro_item.StartFlow(); 
                            _levelNitro_value -= _levelNitro_crement;

                            if (_levelNitro_value < 30)
                            {
                                _levelNitro_crement = 5;
                            }
                            else
                            {
                                _levelNitro_crement = 10;
                            }


                            if (_levelNitro_value >= 0)
                            {
                                LabelNitro_item.Write(_levelNitro_value);
                                SPYWValue(1, _levelNitro_value);
                            }
                            else
                            {
                                _levelNitro_value = 0;
                                FlowOutNitro_item.StopFlow();
                            }
                        }
                        else
                        {
                            if (!Isinner) ValveOutNitro_item.Close();
                            FlowOutNitro_item.StopFlow();
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });

                #endregion

                #region 甲醇出料
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)//true
                    {
                        if (ValveOutMethanol_State)
                        {
                            if (!Isinner) ValveOutMethanol_item.Open();
                            FlowOutMethanol_item.StartFlow();
                            _levelMethanol_value -= _levelMethanol_crement;

                            if (_levelMethanol_value < 30)
                                _levelMethanol_crement = 5;
                            else
                                _levelMethanol_crement = 10;

                            if (_levelMethanol_value >= 0)
                            {
                                SPYWValue(2, _levelMethanol_value);
                                LabelMethanol_item.Write(_levelMethanol_value);
                            }
                            else
                            {
                                _levelMethanol_value = 0;
                                FlowOutMethanol_item.StopFlow();
                            }
                        }
                        else
                        {
                            if (!Isinner) ValveOutMethanol_item.Close();
                            FlowOutMethanol_item.StopFlow();
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });

                #endregion

                #region 氮气阀控制，打开：压力升高
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)//true
                    {
                        if (ValveInN2_State)
                        {
                            if (!Isinner) ValveInN2_item.Open();
                            FlowInN2_item.StartFlow();

                            _pressure_value += _pressure_increment;
                            _pressure_value = Math.Round(_pressure_value, 2);

                            SpPressureValue(_pressure_value);                            
                            LabelPresssure_item.Write(_pressure_value);

                            if (_pressure_value > 0.3)
                            {
                                FlashPressure_item.StartFlow(); //闪烁
                                BeginWarning(WarningType.氮气置换压力过高);
                                _pressure_increment = 0.01;
                            }
                            else
                            {
                                _pressure_increment = 0.02;
                            }

                            if (_pressure_value > 0.2)
                            {
                                _can_open_empty1 = true;
                            }
                            if (can_open_n2 && _pressure_value > 0.2)
                            {
                                _can_open_empty2 = true;
                            }
                        }
                        else
                        {
                           // if (_pressure_value < 0.3)
                                StopWarning(WarningType.氮气置换压力过高);
                            if (!Isinner) ValveInN2_item.Close();
                            FlowInN2_item.StopFlow();
                        }
                        Thread.Sleep(_sleepslow);
                    }
                });

                #endregion

                #region 放空阀控制，打开降压力
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)//true
                    {
                        if (ValveEmpty_State)
                        {
                            if (!Isinner) ValveEmpty_item.Open();
                            FlowOutEmpty_item.StartFlow();

                            _pressure_value = Math.Round(_pressure_value, 2);
                            _pressure_value -= _pressure_decrement;


                            if (_pressure_value < 0.05)
                            {
                                _pressure_decrement = 0.01;
                            }
                            else
                            {
                                _pressure_decrement = 0.04;
                            }

                            if (_pressure_value >= 0.01)
                            {
                                SpPressureValue(_pressure_value);                                
                                LabelPresssure_item.Write(_pressure_value);
                            }
                            else
                            {
                                _pressure_value = 0;
                                LabelPresssure_item.Write(_pressure_value);
                                FlashPressure_item.StopFlow();

                                //反应完 降到0 才能进行氮气置换
                                can_open_n2 = is_reaction_over;
                            }
                        }
                        else
                        {
                            if (!Isinner) ValveEmpty_item.Close();
                            FlowOutEmpty_item.StopFlow();
                            FlashPressure_item.StopFlow();
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });
                #endregion

                #region  加氢，打开：压力升高，流量
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)//true
                    {
                        if (ValveInH2_State)
                        {
                            if (!Isinner) ValveInH2_item.Open();
                            if (!_isreplaceN2_over)
                            {
                                //一票否决，氮气未置换完成，打开氢气阀 属违规操作
                                Vetodown();
                            }
                            _flow_value = Math.Round(_flow_value, 2);
                            LabelFlow_item.Write(_flow_value);
                            FlowInH2_item.StartFlow();

                            //控制反应压力 和 流量
                            if (_pressure_value < 1)
                            {
                                _pressure_increment = 0.06;
                                _flow_crement = 0.5;
                            }
                            else if (_pressure_value >= 1 && _pressure_value <= 2)
                            {
                                _pressure_increment = 0.04;
                                _flow_crement = 0.2;
                            }
                            else
                            {
                                _pressure_increment = 0;
                                _flow_crement = 0;
                                _pressure_decrement = 0.04;
                            }

                            if (_pressure_value >= 2 && _temperature_value >= 98)
                            {
                                is_reaction_over = true;//反应完成
                                _replace_count2 = 1;
                            }

                            if (_pressure_value <= 2)
                            {
                                _pressure_value += _pressure_increment;
                                LabelPresssure_item.Write(_pressure_value);
                                SpPressureValue(_pressure_value);
                                _flow_value += _flow_crement;                                
                                SpFlowValue(_flow_value);
                            }

                            //泄露异常
                            if (_isleakAbnormal && _pressure_value >= 0.6)//2
                            {
                                BeginLeakAbnormal();
                            }

                        }
                        else
                        {
                            if (!Isinner) ValveInH2_item.Close();
                            FlowInH2_item.StopFlow();

                            _flow_value = 0;
                            LabelFlow_item.Write(_flow_value);
                            SpFlowValue(_flow_value);
                        }
                        Thread.Sleep(_sleepslow);
                    }
                });
                #endregion

                #region 蒸汽阀控制
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveInHot_State)
                        {
                            if (!Isinner) ValveInHot_item.Open();
                            FlowInHot_item.StartFlow();

                            //控制反应温度
                            if (_temperature_value >= 98)
                            {
                                _temperature_creament = 0;
                            }
                            else if (_temperature_value > 85)
                            {
                                _temperature_creament = 0.5;
                            }
                            else if (_temperature_value > 60)
                            {
                                _temperature_creament = 1;//1
                            }
                            else
                            {
                                _temperature_creament = 2;//2
                            }


                            if (_temperature_value <= 98)
                            {
                                _temperature_value += _temperature_creament;
                                _temperature_value = Math.Round(_temperature_value, 2);

                                SpTemperatureValue(_temperature_value);
                                LabelTemperature_item.Write(_temperature_value);
                            }
                        }
                        else
                        {
                            if (!Isinner) ValveInHot_item.Close();
                            FlowInHot_item.StopFlow();
                        }
                        Thread.Sleep(_sleepslow);
                    }
                });
                #endregion

                #region 冷水阀控制
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)//true
                    {
                        if (ValveCold_State)
                        {
                            if (!Isinner) ValveCold_item.Open();
                            FlowInCold_item.StartFlow();
                            _temperature_value = Math.Round(_temperature_value, 2);
                            _temperature_value -= _temperature_decreament;

                            if (_temperature_value < 22)
                            {
                                _temperature_decreament = 0;
                            }
                            else if (_temperature_value < 100)
                            {
                                _temperature_decreament = 3;
                                FlashTemperature_item.StopFlow();//取消闪烁
                                _replace_count2 = is_reaction_over ? _replace_count2 = 1 : -1;//反正完成后，开始降温后
                            }

                            SpTemperatureValue(_temperature_value);
                            LabelTemperature_item.Write(_temperature_value);
                        }
                        else
                        {
                            if (!Isinner) ValveCold_item.Close();
                            FlowInCold_item.StopFlow();
                        }
                        Thread.Sleep(_sleepslow);
                    }
                });
                #endregion

                #region 出料阀 控制
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)//true
                    {
                        if (ValveDischarge_State)
                        {
                            if (!Isinner) ValveDischarge_item.Open();
                            FlowDischarge_item.StartFlow();
                        }
                        else
                        {
                            if (!Isinner) ValveDischarge_item.Close();
                            FlowDischarge_item.StopFlow();
                        }
                        Thread.Sleep(_sleepslow);
                    }
                });
                #endregion
            });
        }


        private void CalcFlowAndStep()
        {
            #region 计算
            //硝基物进料
            var nitro_in_item = _steps.Where(i => i.Status[StatusName.硝基物进料阀] == open).OrderByDescending(i => i.Status[StatusName.硝基物液位]).FirstOrDefault();

            //甲醇进料
            var methenol_in_item = _steps.Where(i => i.Status[StatusName.甲醇进料阀] == open).OrderByDescending(i => i.Status[StatusName.甲醇液位]).FirstOrDefault();


            //测试用 当做第一步
            //硝基物出料
            var nitro_out_item = _steps.Where(i => i.Status[StatusName.硝基物放料阀] == open)
                .OrderBy(i => i.Status[StatusName.硝基物液位]).OrderByDescending(i => i.Date).FirstOrDefault();

            //甲醇出料
            var methenol_out_item = _steps.Where(i => i.Status[StatusName.甲醇放料阀] == open)
                .OrderBy(i => i.Status[StatusName.甲醇液位]).OrderByDescending(i => i.Date).FirstOrDefault();

            //氮气置换，在通入2种物料后进行 注意2个date
            //氮气1
            var n2_pressure_item1 = _steps.Where(i => i.Status[StatusName.氮气阀1] == open)
                .OrderByDescending(i => i.Status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault();

            //放空1 
            var o2_pressure_item1 = n2_pressure_item1 != null ? _steps.Where(i => i.Status[StatusName.放空阀1] == open && i.Date > n2_pressure_item1.Date)
                .OrderBy(i => i.Status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault() : null;

            //氮气2
            var n2_pressure_item2 = o2_pressure_item1 != null ? _steps.Where(i => i.Status[StatusName.氮气阀2] == open && i.Date > o2_pressure_item1.Date)
                .OrderByDescending(i => i.Status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault() : null;

            //放空2 
            var o2_pressure_item2 = n2_pressure_item2 != null ? _steps.Where(i => i.Status[StatusName.放空阀2] == open && i.Date > n2_pressure_item2.Date)
                .OrderBy(i => i.Status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault() : null;

            //开搅拌 一直开 直到反应结束,最后加

            //反应：加氢同时加蒸汽
            //加氢
            //var h2_item = o2_pressure_item2 != null ? _steps.Where(i => i.status[StatusName.氢气阀] == open && i.Date > o2_pressure_item2.Date)
            //    .OrderByDescending(i => i.status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault() : null;
            var h2_item = _steps.Where(i => i.Status[StatusName.氢气阀] == open)
                .OrderByDescending(i => i.Status[StatusName.压力]).ThenByDescending(i => i.Date).FirstOrDefault();

            //加热
            //var hot_temperature_item = o2_pressure_item2 != null ? _steps.Where(i => i.status[StatusName.蒸汽阀] == open && i.Date > o2_pressure_item2.Date)
            //    .OrderByDescending(i => i.status[StatusName.温度]).ThenByDescending(i => i.Date).FirstOrDefault() : null;
            var hot_temperature_item = _steps.Where(i => i.Status[StatusName.蒸汽阀] == open)
                .OrderByDescending(i => i.Status[StatusName.温度]).ThenByDescending(i => i.Date).FirstOrDefault();

            //反应结束关闭蒸汽阀 和 氢气阀  (开着的0个 说明关闭) 一直到最后出料前都要关闭

            //放空 置换体现

            //降温和出料
            //降温
            //var cold_temperature_item = hot_temperature_item != null ? _steps.Where(i => i.status[StatusName.冷水阀] == open && i.Date > hot_temperature_item.Date)
            //    .OrderBy(i => i.status[StatusName.温度]).OrderByDescending(i => i.Date).FirstOrDefault() : null;
            var cold_temperature_item = _steps.Where(i => i.Status[StatusName.冷水阀] == open && hot_temperature_item != null && i.Date > hot_temperature_item.Date)
                .OrderBy(i => i.Status[StatusName.温度]).OrderByDescending(i => i.Date).FirstOrDefault();

            //氮气置换 7-15在加热后，后面判断是否在降温后
            //氮气1
            var n2_pressure_item3 = _steps.Where(i => hot_temperature_item != null && i.Status[StatusName.氮气阀3] == open && i.Date > hot_temperature_item.Date)
                .OrderByDescending(i => i.Status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault();

            //放空1
            var o2_pressure_item3 = _steps.Where(i => n2_pressure_item3 != null && i.Status[StatusName.放空阀3] == open && i.Date > n2_pressure_item3.Date)
                .OrderBy(i => i.Status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault();

            //氮气2
            var n2_pressure_item4 = _steps.Where(i => i.Status[StatusName.氮气阀4] == open && o2_pressure_item3 != null && i.Date > o2_pressure_item3.Date)
                .OrderByDescending(i => i.Status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault();

            //放空2
            var o2_pressure_item4 = _steps.Where(i => i.Status[StatusName.放空阀4] == open && n2_pressure_item4 != null && i.Date > n2_pressure_item4.Date)
                 .OrderBy(i => i.Status[StatusName.压力]).OrderByDescending(i => i.Date).FirstOrDefault();

            //2015-7-24 改成在降温之后
            //关搅拌 一直开 直到反应结束,最后加
            var stir_open_first = _steps.FirstOrDefault(i => i.Status[StatusName.搅拌阀] == open);//首次打开的时间
            var stir_not_open_count = cold_temperature_item != null ?
                _steps.Count(i => i.Status[StatusName.搅拌阀] == close
                    && stir_open_first != null && i.Date > stir_open_first.Date
                    && i.Date < cold_temperature_item.Date) : -1;


            //放料
            var discharge_count = cold_temperature_item != null ? _steps.Count(i => i.Status[StatusName.放料阀] == open && i.Date > cold_temperature_item.Date) : -1;
            var discharge_open_item = discharge_count > 0 ? _steps.Where(i => i.Status[StatusName.放料阀] == open && i.Date > cold_temperature_item.Date).OrderBy(i => i.Date).FirstOrDefault() : null;

            //出料之前关闭搅拌 
            var stir_close_count = discharge_open_item != null ? _steps.Count(i => i.Status[StatusName.搅拌阀] == close && i.Date < discharge_open_item.Date) : -1;

            //反应结束关闭蒸汽阀 和 氢气阀  (开着的0个 说明关闭) 一直到最后 氮气置换 完成前都要关闭
            var h2_close_count = h2_item != null && cold_temperature_item != null ? _steps.Count(i => i.Status[StatusName.氢气阀] == open && i.Date > h2_item.Date && i.Date < cold_temperature_item.Date) : -1;
            var hot_close_count = hot_temperature_item != null ? _steps.Count(i => i.Status[StatusName.蒸汽阀] == open && i.Date > hot_temperature_item.Date && i.Date < cold_temperature_item.Date) : -1;

            #endregion
            #region 添加步骤
            #region 进料出料
            //1.进料
            //1.1 硝基物进料
            if (nitro_in_item != null)
            {
                var value = nitro_in_item.Status[StatusName.硝基物液位];
                if (value > 300)
                {
                    AddCompose("硝基物进料：液位300-600");
                }
                else
                {
                    if (value != -1)
                        AddCompose("硝基物进料：液位低于300");
                }
            }


            //1.2 甲醇进料
            if (methenol_in_item != null)
            {
                var value = methenol_in_item.Status[StatusName.甲醇液位];
                if (value > 200)
                    AddCompose("甲醇进料：液位200-400");
                else
                {
                    if (value != -1)
                        AddCompose("甲醇进料：液位低于200");
                }
            }


            //2.出料
            //2.1硝基物出料
            if (nitro_out_item != null)
            {
                double nitro_out_minvalue = -1;
                double nitro_in_maxvalue = -1;

                nitro_out_minvalue = nitro_out_item.Status[StatusName.硝基物液位];
                nitro_in_maxvalue = 340;// nitro_in_item.Status[StatusName.硝基物液位];//340



                if (nitro_out_minvalue != -1)
                {
                    var diff_nitro = nitro_in_maxvalue - nitro_out_minvalue;
                    if (diff_nitro > 350)
                        AddCompose("硝基物放料：液位差高于350");
                    else if (diff_nitro >= 300)
                        AddCompose("硝基物放料：液位差300-350");
                    else
                        AddCompose("硝基物放料：液位差低于300");
                }
            }

            //2.1
            if (methenol_out_item != null)
            {
                var methenol_out_minvalue = methenol_out_item.Status[StatusName.甲醇液位];
                var methenol_in_maxvalue = 240;// methenol_in_item.Status[StatusName.甲醇液位];//240
                if (methenol_out_minvalue != -1)
                {
                    var diff_methenol = methenol_in_maxvalue - methenol_out_minvalue;
                    if (diff_methenol > 250)
                        AddCompose("甲醇进料：液位差高于250");
                    else if (diff_methenol > 200)
                        AddCompose("甲醇放料：液位差200");
                    else
                        AddCompose("甲醇进料：液位差低于200");
                }
            }

            #endregion

            #region 置换
            //3.氮气置换
            //3.1 第1次置换 
            if (n2_pressure_item1 != null)
            {
                var pressure_value = n2_pressure_item1.Status[StatusName.压力];
                if (pressure_value >= 0.3)
                    AddCompose(string.Format("第{0}次氮气置换：气压>0.3MPa时未关闭氮气阀，压力过高", 1));
                else if (pressure_value >= 0.2 && pressure_value < 0.3)
                    AddCompose(string.Format("第{0}次氮气置换：打开氮气阀，充氮气至0.2-0.3MPa", 1));
            }
            if (o2_pressure_item1 != null)
            {
                var pressure_value = o2_pressure_item1.Status[StatusName.压力];
                if (pressure_value <= 0.01)
                {
                    AddCompose(string.Format("第{0}次氮气置换：打开放空阀，降压至0MPa", 1));
                    AddCompose(string.Format("第{0}次氮气置换：完成", 1));
                }
            }

            //3.2 第2次置换 
            if (n2_pressure_item2 != null)
            {
                var pressure_value = n2_pressure_item2.Status[StatusName.压力];
                if (pressure_value >= 0.3)
                    AddCompose(string.Format("第{0}次氮气置换：气压>0.3MPa时未关闭氮气阀，压力过高", 2));
                else if (pressure_value >= 0.2 && pressure_value < 0.3)
                    AddCompose(string.Format("第{0}次氮气置换：打开氮气阀，充氮气至0.2-0.3MPa", 2));
            }
            if (o2_pressure_item2 != null)
            {
                var pressure_value = o2_pressure_item2.Status[StatusName.压力];
                if (pressure_value <= 0.01)
                {
                    AddCompose(string.Format("第{0}次氮气置换：打开放空阀，降压至0MPa", 2));
                    AddCompose(string.Format("第{0}次氮气置换：完成", 2));
                }
            }
            #endregion


            //4.开搅拌
            if (stir_not_open_count == 0)
                AddCompose("搅拌釜：打开");

            //5.加氢反应
            //5.1 加氢
            if (h2_item != null)
            {
                var h2_value = h2_item.Status[StatusName.压力];
                AddCompose(h2_value >= 2 ? "加氢反应：充氢气使压力升至2MPa" : "加氢反应：充氢气过程中，压力不足2MPa,关闭氢气阀");
            }

            //5.2 通入蒸汽
            if (hot_temperature_item != null)
            {
                var value = hot_temperature_item.Status[StatusName.温度];
                if (value >= 98)
                    AddCompose("加氢反应：充蒸汽是反应釜温度升至98℃");
                else
                    AddCompose("加氢反应：充蒸汽过程中，温度过低，关闭蒸汽阀");
            }

            //5.3反应完成，关闭蒸汽阀和氢气阀
            if (h2_close_count == 0)
                AddCompose("加氢反应完成：关闭氢气阀");
            if (hot_close_count == 0)
                AddCompose("加氢反应完成：关闭蒸汽阀");

            //6.降温与出料
            //6.1降温到50°
            if (cold_temperature_item != null)
            {
                var value = cold_temperature_item.Status[StatusName.温度];
                if (value < 50)
                    AddCompose("降温：打开冷水阀，降温至0-50℃");
                else
                    AddCompose("降温：未降到50℃以下");
            }

            //6.2氮气置换
            if (n2_pressure_item3 != null)
            {
                var pressure_value = n2_pressure_item3.Status[StatusName.压力];
                if (pressure_value >= 0.3)
                    AddCompose(string.Format("反应后，第{0}次氮气置换：气压>0.3MPa时未关闭氮气阀，压力过高", 1));
                else if (pressure_value >= 0.2 && pressure_value < 0.3)
                    AddCompose(string.Format("反应后，第{0}次氮气置换：打开氮气阀，充氮气至0.2-0.3MPa", 1));


                //是否在降温后
                if (cold_temperature_item != null)
                {
                    if (n2_pressure_item3.Date < cold_temperature_item.Date)
                    {
                        AddCompose("降温到50℃之前打开氮气阀");
                    }
                }
            }
            if (o2_pressure_item3 != null)
            {
                var pressure_value = o2_pressure_item3.Status[StatusName.压力];
                if (pressure_value <= 0.01)
                {
                    AddCompose(string.Format("反应后，第{0}次氮气置换：打开放空阀，降压至0MPa", 1));
                    AddCompose(string.Format("反应后，第{0}次氮气置换：完成", 1));
                }
            }




            //6.3 第2次置换 
            if (n2_pressure_item4 != null)
            {
                var pressure_value = n2_pressure_item4.Status[StatusName.压力];
                if (pressure_value >= 0.3)
                    AddCompose(string.Format("反应后，第{0}次氮气置换：气压>0.3MPa时未关闭氮气阀，压力过高", 2));
                else if (pressure_value >= 0.2 && pressure_value < 0.3)
                    AddCompose(string.Format("反应后，第{0}次氮气置换：打开氮气阀，充氮气至0.2-0.3MPa", 2));
            }
            if (o2_pressure_item4 != null)
            {
                var pressure_value = o2_pressure_item4.Status[StatusName.压力];
                if (pressure_value <= 0.01)
                {
                    AddCompose(string.Format("反应后，第{0}次氮气置换：打开放空阀，降压至0MPa", 2));
                    AddCompose(string.Format("反应后，第{0}次氮气置换：完成", 2));
                }
            }

            //6.4关闭搅拌
            if (stir_close_count > 0)
            {
                AddCompose("搅拌釜：关闭");
            }
            //6.5出料
            if (discharge_count > 0)
            {
                AddCompose("出料：打开出料阀");
            }


            //异常处理

            #endregion
        } 
        #endregion

        #region 私有方法
        protected override void Vetodown()
        {
            SendMessage("在含氧量不合格的情况下打开氢气阀，属于严重违规操作，停止考核！");
            _isvetodown = true;
            _listenCts.Cancel();
        }

        #endregion


        #region 写串口数据
        void SpFlowValue(double value)
        {
            WriteFlowValue(_llcmd, 1, value);
            WriteAIvalue(_aicmd, 3, value);
        }

        void SpPressureValue(double value)
        {
            WritePressureValue(_ylcmd, value);
            WriteAIvalue(_aicmd, 1, value);
        }

        void SpTemperatureValue(double value)
        {
            WriteTemperatureValue(_wdcmd, value);
            WriteAIvalue(_aicmd, 2, value);
        }

        /// <summary>
        /// 设置液位值
        /// </summary>
        /// <param name="index">液位索引：1或者2</param>
        /// <param name="value"></param>

        void SPYWValue(int index, double value)
        {
            if (Isinner) return;
            double write_value = 0;
            switch (index)
            {
                case 1:
                    write_value = 255 * value / 600;
                    break;
                case 2:
                    write_value = 255 * value / 400;
                    break;
            }
            write_value = Math.Round(write_value, 0);

            string cmdvalue = write_value.ToString().PadLeft(3, '0');
            string cmd = string.Format(_ywcmd, index, cmdvalue);
            lock (this)
            {
                Thread.Sleep(150);
                if(_serialPort.IsOpen)
                _serialPort.Write(cmd);
            }
        }

        #endregion

        #region 操作继电器
        /// <summary>
        /// 写继电器
        /// </summary>
        /// <param name="number">0-128， </param>
        void SPWriteTool(int number)
        {
            if (Isinner) return;
            WriteTool(_relaycmd, number);
        }

        void CloseAllRelay()
        {
            SPWriteTool(0);
        }

        /// <summary>
        /// 开始预警
        /// </summary>
        /// <param name="type">预警类型</param>
        void BeginWarning(WarningType type)
        {
            if (!_warningtypes.Contains(type))
            {
                FlashWarning_item.Open();
                _warningtypes.Add(type);
                _relayCommand = _relayCommand | _warning1number;
                _relayCommand = _relayCommand | _warning2number;
                SPWriteTool(_relayCommand);
            }
        }

        void StopWarning(WarningType type)
        {
            if (_warningtypes.Contains(type))
            {
                FlashWarning_item.Close();
                _relayCommand = (~_warning1number) & _relayCommand;
                _relayCommand = (~_warning2number) & _relayCommand;
                SPWriteTool(_relayCommand);
                _warningtypes.Remove(type);
            }
        }

        /// <summary>
        /// 开始泄漏
        /// </summary>
        void BeginLeak()
        {
            FlashWarning_item.Open();
            _relayCommand = _relayCommand | _fognumber;
            SPWriteTool(_relayCommand);
            Thread.Sleep(500);
            StopLeak();
        }
        /// <summary>
        /// 停止泄漏
        /// </summary>
        void StopLeak()
        {
            FlashWarning_item.Close();
            _relayCommand = _relayCommand & (~_fognumber);
            SPWriteTool(_relayCommand);
        }

        void BeginStir()
        {
            _relayCommand = _relayCommand | _stirnumber;
            SPWriteTool(_relayCommand);
        }

        void StopStir()
        {
            _relayCommand = _relayCommand & (~_stirnumber);
            SPWriteTool(_relayCommand);
        }
        #endregion

        #region 枚举定义
        /// <summary>
        /// 组态字段-字符串
        /// </summary>
        enum FiledName
        {
            /// <summary>
            /// 硝基物液位
            /// </summary>
            LabelNitro,
            /// <summary>
            /// 甲醇液位
            /// </summary>
            LabelMethanol, LabelTemperature, LabelPresssure, LabelFlow, LabelOxygen,
            
            //阀门
            ValveInNitro, ValveInMethanol, ValveOutNitro, ValveOutMethanol, ValveInN2, ValveEmpty, ValveCold, ValveInHot, ValveInH2, ValveDischarge, ValveAutoEmpty, ValveICutoff, ValveOverNitro, ValveOverMethanol,
            ValveStir,ValveStop,
            //管道
            FlowInNitro,FlowInMethanol,FlowOutMethanol,FlowOutNitro,FlowOutEmpty,FlowInCold,FlowInHot,FlowInH2,FlowDischarge,FlowInN2,
            //flash
            FlashPressure, FlashTemperature,
            /// <summary>
            /// 催化剂
            /// </summary>
            FlashCatalyst,
            /// <summary>
            /// 搅拌釜
            /// </summary>
            FlashStir, FlashWarning
        }
        /// <summary>
        /// 状态名称
        /// </summary>
        enum StatusName
        {
            硝基物进料阀, 甲醇进料阀, 硝基物放料阀, 甲醇放料阀,
            硝基物液位, 甲醇液位, 温度, 压力, 流量, 自动放空阀, 冷水阀, 蒸汽阀, 氢气阀, 紧急切断阀, 放料阀, 搅拌阀,
            放空阀1, 氮气阀1, 放空阀2, 氮气阀2, 放空阀3, 氮气阀3, 放空阀4, 氮气阀4,
        }

        enum WarningType
        {
            甲醇液位过高,
            硝基物液位过高,
            通入甲醇过量,
            通入硝基物过量,
            氮气置换压力过高,
            温度异常,
            压力异常,
            泄漏,
            反应釜压力过高,
        }

        #endregion
    }
}
